package com.apkcore.core.toast

import android.app.AppOpsManager
import android.app.NotificationManager
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import com.apkcore.core.cp.ApkcoreContentProvider
import com.apkcore.core.ext.dp2px
import com.apkcore.core.ext.isAppForeground
import com.apkcore.core.ext.isDebug
import com.apkcore.core.ext.sp2px
import com.apkcore.core.util.UiUtil
import com.apkcore.core.toast.NotificationToast
import com.apkcore.core.toast.SafeToast
import java.lang.reflect.InvocationTargetException


/**
 * 参考https://github.com/getActivity/Toaster/tree/master
 */
object Toaster {
    private var toast: Toast? = null

    fun debugShow(
        message: String,
        gravity: Int = Toaster.gravity,
        duration: Int = Toast.LENGTH_SHORT,
    ) {
        if (ApkcoreContentProvider.appContext.isDebug()) {
            show(message, gravity, duration)
        }
    }

    private var textSize = 14.sp2px()
    private var gravity = Gravity.CENTER

    fun setGlobalTextSize(textSize: Float): Toaster {
        Toaster.textSize = textSize
        return this
    }

    fun setGlobalGravity(gravity: Int): Toaster {
        Toaster.gravity = gravity
        return this
    }

    fun show(
        message: String,
        gravity: Int = Toaster.gravity,
        duration: Int = Toast.LENGTH_SHORT,
        textSize: Float? = null
    ) {
        try {
            delayedShow(message, gravity, duration, 0, textSize)
        }catch (e:Exception){
//            e.printStackTrace()
        }
    }


    fun delayedShow(
        message: String,
        gravity: Int = Toaster.gravity,
        duration: Int = Toast.LENGTH_SHORT,
        delayed: Long = 2000,
        textSize: Float? = null
    ) {
        UiUtil.runOnUiThread(delayed) {
            val context = ApkcoreContentProvider.appContext
            if (!context.isAppForeground()) {
                toast?.cancel()  // 取消当前显示的 Toast
                toast = Toast.makeText(context, message, Toast.LENGTH_SHORT)
                toast?.show()
                return@runOnUiThread
            }
            toast?.cancel()
            toast = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) {
                // 处理 Android 7.1 上 Toast 在主线程被阻塞后会导致报错的问题
                SafeToast(context.applicationContext)
            } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
                !areNotificationsEnabled(context.applicationContext)
            ) {
                // 处理 Toast 关闭通知栏权限之后无法弹出的问题
                // 通过查看和对比 NotificationManagerService 的源码
                // 发现这个问题已经在 Android 10 版本上面修复了
                // 但是 Toast 只能在前台显示，没有通知栏权限后台 Toast 仍然无法显示
                // 并且 Android 10 刚好禁止了 Hook 通知服务
                // 已经有通知栏权限，不需要 Hook 系统通知服务也能正常显示系统 Toast
                NotificationToast(context.applicationContext)
            } else {
                Toast(context.applicationContext)
            }
            val textView = createTextView(context, textSize)
            textView.text = message
            toast?.view = textView
            toast?.duration = duration
            toast?.setGravity(gravity, 0, 0)

            toast?.show()
        }
    }

    private fun createTextView(context: Context, textSize: Float?): TextView {
        val textView = TextView(context)
        textView.setId(android.R.id.message)
        textView.setGravity(gravity)
        textView.setTextColor(Color.WHITE)
        Log.d("TAG", "createTextView: $textSize ${Toaster.textSize}")
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize ?: Toaster.textSize)

        val horizontalPadding = 24.dp2px()
        val verticalPadding = 16.dp2px()

        // 适配布局反方向特性
        textView.setPaddingRelative(
            horizontalPadding,
            verticalPadding,
            horizontalPadding,
            verticalPadding
        )

        textView.setLayoutParams(
            ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
        )

        val backgroundDrawable = getBackgroundDrawable()
        // 设置背景
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            textView.background = backgroundDrawable
        } else {
            textView.setBackgroundDrawable(backgroundDrawable)
        }

        // 设置 Z 轴阴影

        // 设置 Z 轴阴影
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            textView.z = 3.dp2px().toFloat()
        }
        return textView
    }

    private fun getBackgroundDrawable(): Drawable {
        val drawable = GradientDrawable()
        // 设置颜色
        drawable.setColor(-0x4d000000)
        // 设置圆角
        drawable.setCornerRadius(10.dp2px().toFloat())
        return drawable
    }

    private fun areNotificationsEnabled(context: Context): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return context.getSystemService(NotificationManager::class.java)
                .areNotificationsEnabled()
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 参考 Support 库中的方法： NotificationManagerCompat.from(context).areNotificationsEnabled()
            val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
            return try {
                val method = appOps.javaClass.getMethod(
                    "checkOpNoThrow",
                    Integer.TYPE, Integer.TYPE, String::class.java
                )
                val field = appOps.javaClass.getDeclaredField("OP_POST_NOTIFICATION")
                val value = field[Int::class.java] as Int
                method.invoke(
                    appOps, value, context.applicationInfo.uid,
                    context.packageName
                ) as Int == AppOpsManager.MODE_ALLOWED
            } catch (e: NoSuchMethodException) {
                e.printStackTrace()
                true
            } catch (e: NoSuchFieldException) {
                e.printStackTrace()
                true
            } catch (e: InvocationTargetException) {
                e.printStackTrace()
                true
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
                true
            } catch (e: RuntimeException) {
                e.printStackTrace()
                true
            }
        }
        return true
    }

}
